<template>
	<div class="json-schema-editor">
		<template v-if="props.root">
			<base-header v-bind="props" />
		</template>
		<div class="data-row">
			<!-- 添加/删除操作列 -->
			<div class="ant-col-setting" v-if="!disabled">
				<el-button
					v-if="
						pickValueKeyCopy != dataKey ||
						pickValueTypeCopy != pickValue.type ||
						pickValueTitleCopy != pickValue.title ||
						(pickValue.type != 'object' && !!dataValue && dataValueCopy != dataValue)
					"
					link
					class="iconfont iconcirclecheckfull"
					style="color: green"
					@click="
						() => {
							// props.jsonValue[dataKey] = dataValue;
							pickValueKeyCopy = dataKey;
							// pickValueTypeCopy = pickValue.type;
							pickValueTitleCopy = pickValue.title;
							// dataValueCopy = dataValue;
							mittBus.emit('addJsonValue', { key: path, data: dataValue, label: pickValue.title });
						}
					"
				/>
				<div v-else class="empty-btn"></div>
			</div>

			<!-- schema 字段key -->
			<div class="ant-col-name">
				<div class="ant-col-name-c pl-1" :style="{ marginLeft: 10 * deep + 'px' }">
					<el-button
						v-if="pickValue.type === 'object'"
						link
						@click="hidden = !hidden"
						:class="`iconfont ${hidden ? 'iconbx-caret-right' : 'iconbx-caret-down'}`"
					/>
					<span v-else style="display: inline-block; width: 25px"></span>
					<template v-if="!root">
						<!-- 必填选项 -->
						<el-input
							v-model="dataKey"
							class="ant-col-name-input"
							@blur="onInputName"
							placeholder="标识必须是字母开头"
							disabled
						/>
					</template>
					<template v-else>{{ pickValue.title }}</template>
				</div>
			</div>

			<!-- schema type类型 -->
			<div class="ant-col-type">
				<el-select v-if="!root" v-model="pickValue.type" disabled class="ant-col-type-select" @change="onChangeType">
					<el-option :key="key" v-for="(name, key) in TYPE_NAME" :value="key" :label="name">{{ name }}</el-option>
				</el-select>
			</div>

			<!-- schema title标题 -->
			<div class="ant-col-title">
				<el-input
					v-if="!root"
					v-model="pickValue.title"
					class="ant-col-title"
					:placeholder="local['title']"
					:disabled="disabled"
				/>
			</div>

			<!-- profile 扩展数据列 -->
			<div class="ant-col-values truncate" :title="$t('jsonschemaform.tip_title.data')">
				<template v-if="!pickValue.properties">
					<!-- 扩展列数据显示：配置 -->
					<el-input-number
						v-if="pickValue.type == 'number'"
						v-model="dataValue"
						:placeholder="`请输入${pickValue.title || pickKey}内容`"
						@input="changeJsonValue"
						:disabled="disabled"
					/>
					<div v-else-if="pickValue.type == 'object'"></div>
					<el-input
						v-else
						v-model="dataValue"
						:placeholder="`请输入${pickValue.title || pickKey}内容`"
						@input="changeJsonValue"
						:disabled="disabled"
					/>
				</template>
			</div>
			<!-- profile 扩展数据列 -->
			<div v-if="pickValue.type == 'object' && deep == 1" class="ant-col-operate text-center" style="width: 80px">
				<!-- 网页信息 -->
				<el-link type="primary" :class="`iconfont iconbx-check-square`" @click="clickValueIcon('func')"> 设置参数 </el-link>
			</div>
		</div>
		<template v-if="isArray">
			<JsonSchemaFormFunc
				:value="{ items: pickValue.items }"
				:deep="deep + 1"
				:disabled="disabled"
				isItem
				:root="false"
				:path="`${path ? path + '.' : ''}items`"
				class="children"
				:lang="lang"
				:extType="extType"
				:jsonValue="jsonValue"
				:jsonParam="jsonParam"
				:custom="custom"
				:is-sensor="isSensor"
				:mode="mode"
			/>
		</template>
		<template v-if="!hidden && pickValue.properties && !isArray">
			<JsonSchemaFormFunc
				v-for="(item, key) in pickValue.properties"
				:value="{ [key]: item }"
				:parent="pickValue"
				:key="item"
				:deep="deep + 1"
				:extType="extType"
				:root="false"
				:path="`${path ? path + '.' : ''}${key}`"
				class="children"
				:lang="lang"
				:jsonValue="jsonValue"
				:jsonParam="jsonParam"
				:custom="custom"
				:is-sensor="isSensor"
				:mode="mode"
				:disabled="disabled"
			/>
		</template>
	</div>
</template>
<script setup lang="ts">
import { DataPreview } from "@/enums/dataPreview";
import mittBus from "@/utils/mittBus";
import jsonpath from "jsonpath";
import { JsonSchemaEmitParam } from "./interface/jsonschema";
import LocalProvider from "./LocalProvider/index";
import { TYPE, TYPE_NAME } from "./type/type";
import { renamePropertyAndKeepKeyPrecedence } from "./util";
import BaseHeader from "./components/BaseHeader.vue";
import "./index.scss";
import { SchemaInfo } from "./interface";
import { ComputedRef } from "vue";
import { assJsonpathData } from "../../utils/util";
const props = defineProps({
	value: {
		type: Object,
		required: true
	},
	disabled: {
		//name不可编辑，根节点name不可编辑,数组元素name不可编辑
		type: Boolean,
		default: false
	},
	isItem: {
		//是否数组元素
		type: Boolean,
		default: false
	},
	deep: {
		// 节点深度，根节点deep=0
		type: Number,
		default: 0
	},
	root: {
		//是否root节点
		type: Boolean,
		default: true
	},
	parent: {
		//父节点
		type: Object,
		default() {
			return {};
		}
	},
	custom: {
		//enable custom properties
		type: Boolean,
		default: false
	},
	lang: {
		// i18n language
		type: String,
		default: "zh_CN"
	},
	path: {
		type: String,
		default: ""
	},
	// isEditer: {
	// 	//编辑模式：编辑模式显示完整编辑项，只读模式只显示节点label+数据内容
	// 	type: Boolean,
	// 	default: true
	// },
	extType: {
		//扩展Type选项：扩展key=type的数据类型选择
		type: Boolean,
		default: false
	},
	mode: {
		//页面模式，定义schema=conf，回填内容=preview
		type: String,
		default: "conf"
	},
	isSensor: {
		//是否是变量模型
		type: Boolean,
		default: false
	},
	jsonValue: {
		//扩展的json字段值
		type: Object,
		default() {
			return {};
		}
	},
	jsonParam: {
		//扩展的参数
		type: Object,
		default() {
			return {};
		}
	}
});

const dataValue = ref<any>();
const dataParam = ref<any>();
onMounted(() => {
	initDataFormJsonValue();
	dataValueCopy.value = dataValue.value;
});
watch(
	() => props.jsonValue,
	() => {
		initDataFormJsonValue();
	},
	{ deep: true }
);
const initDataFormJsonValue = () => {
	if (props.path) {
		if (props.deep == 1) {
			dataValue.value = jsonpath.value(props.jsonValue, assJsonpathData(props.path, "$"));
		} else {
			dataValue.value = jsonpath.value(props.jsonValue, assJsonpathData(props.path, "$.."));
		}
		dataParam.value = jsonpath.value(props.jsonParam, assJsonpathData(props.path, "$.."));
	}
	//根据内容自动更新schema类型
	// if (typeof dataValue.value == "number") {
	// 	pickValue.value.type = "number";
	// }
	//根据schema，强制更新数值
	// if (pickValue.value.type == "number") {
	// 	let val = Number(dataValue.value);
	// 	dataValue.value = isNaN(val) ? 0 : val;
	// 	//强制更新profile内容，避免页面未做编辑
	// 	jsonpath.value(props.jsonValue, assJsonpathData(props.path, "$.."), dataValue.value);
	// }
};
const clickValueIcon = (type?: any) => {
	if (!type) {
		let dp = Object.values(DataPreview).find(item => pickValue.value.type == item.type);
		type = dp;
	}

	let param: JsonSchemaEmitParam = {
		dataPath: props.path,
		dataType: type?.type || DataPreview.historyChart.type,
		dataKey: dataKey.value,
		dataValue: dataValue.value,
		schemaInfo: pickValue.value
	};
	mittBus.emit("clickValueIcon", param);
};
const changeJsonValue = (val: any) => {
	if (props.deep > 0 && props.path != dataKey.value) {
		jsonpath.value(props.jsonValue, assJsonpathData(props.path, "$.."), val);
	} else {
		props.jsonValue[dataKey.value] = val;
	}
};

const renamePropertyAndKeepKeyPrecedenceProfile = ({ oldKey }: { newKey?: string; oldKey: string }) => {
	let ppath = props.path.replace(`.${oldKey}`, "");
	//获取原来节点
	let oldNode = jsonpath.query(props.jsonValue, assJsonpathData(ppath, "$.."))[0] || {};
	//设置到新节点
	jsonpath.value(props.jsonValue, assJsonpathData(props.path, "$.."), oldNode);
	//删除原节点
	eval(`delete props.jsonValue['${ppath}']`);
	// console.log(JSON.stringify(props.jsonValue, null, 2));
};

const pickValue: ComputedRef<SchemaInfo | any> = computed(() => {
	return Object.values(props.value)[0];
});
const pickKey = computed(() => {
	return Object.keys(props.value)[0];
});
const isArray = computed(() => {
	return pickValue.value.type === "array";
});
const advanced = computed(() => {
	// return TYPE[pickValue.value.type as string];
	let res;
	switch (pickValue.value.type) {
		case "object":
			res = TYPE.object;
			break;
		case "string":
			res = TYPE.object;
			break;
		case "array":
			res = TYPE.object;
			break;
		case "boolean":
			res = TYPE.object;
			break;
		case "integer":
			res = TYPE.object;
			break;
		case "number":
			res = TYPE.object;
			break;
		case "custom":
			res = TYPE.custom;
			break;
	}
	return res;
});
const advancedAttr = computed(() => {
	// return TYPE[pickValue.value.type].attr;
	let res: any = advanced.value;
	return res?.attr || {};
});
const ownProps = computed(() => {
	return ["type", "title", "properties", "items", "required", ...Object.keys(advancedAttr.value)];
});

const hidden = ref(false);
const addProp = reactive<any>({ key: "", value: "" }); // 自定义属性
const customProps = reactive<any>([]);
const customing = ref(false);
const local = LocalProvider(props.lang);
const dataKey = ref<string>("");
watchEffect(() => {
	dataKey.value = pickKey.value;
});
const onInputName = (e: any) => {
	let newKey = e.target.value;
	// //纯数字key增加key前缀
	// if (!newKey || !isNaN(Number(newKey))) {
	// 	showMsg("节点标识非法，已自动修正", false);
	// 	newKey = "key_" + newKey;
	// }
	const oldKey = pickKey.value;
	if (oldKey === newKey) return;
	// 替换key名
	renamePropertyAndKeepKeyPrecedence(props.parent?.properties, [oldKey, newKey]);
	// 替换profile名
	renamePropertyAndKeepKeyPrecedenceProfile({ oldKey: oldKey, newKey: newKey });

	// required重新设置
	const requireds = props.parent?.required || [];
	const oldIndex = requireds.indexOf(oldKey);
	if (requireds.length > 0 && oldIndex > -1) {
		requireds.splice(oldIndex, 1);
		requireds.push(newKey);
		// eslint-disable-next-line vue/no-mutating-props
		props.parent["required"] = [...new Set(requireds)];
	}
};
const onChangeType = () => {
	if (pickValue.value.type == "object") {
		dataValue.value = {};
		jsonpath.value(props.jsonValue, assJsonpathData(props.path, "$.."), dataValue.value);
	} else if (pickValue.value.type == "string") {
		jsonpath.value(props.jsonValue, assJsonpathData(props.path, "$.."), dataValue.value + "");
	} else if (pickValue.value.type == "number") {
		jsonpath.value(props.jsonValue, assJsonpathData(props.path, "$.."), Number(dataValue.value));
	}
	parseCustomProps();
	// 删除自定义属性
	customProps.forEach((item: any) => {
		delete pickValue.value[item.key];
	});
	customProps.splice(0, customProps.length);

	delete pickValue.value["properties"];
	delete pickValue.value["items"];
	delete pickValue.value["required"];
	delete pickValue.value["format"];
	delete pickValue.value["enum"];

	if (isArray.value) {
		pickValue.value["items"] = { type: "string" };
	}
};

const parseCustomProps = () => {
	let ops = ownProps.value;
	Object.keys(pickValue.value).forEach(key => {
		if (ops.indexOf(key) === -1) {
			confirmAddCustomNode({ key: key, value: pickValue.value[key] });
			// $delete(pickValue.value,key)
		}
	});
};

const confirmAddCustomNode = (prop: { key: string; value: any }) => {
	const p = prop.key ? prop : addProp;
	let existKey = false;
	customProps.forEach((item: any) => {
		if (item.key === p.key) {
			existKey = true;
		}
	});
	if (existKey) return;
	customProps.push(p);
	addProp.key = "";
	addProp.value = "";
	customing.value = false;
};

const pickValueKeyCopy = ref(dataKey.value);
const pickValueTypeCopy = ref(pickValue.value.type);
const pickValueTitleCopy = ref(pickValue.value.title);
const dataValueCopy = ref(dataValue.value);
</script>
